#include "../server.hpp"
//#include "../Gitserver.hpp"

#include <regex>
#include <fstream> 
#include <unordered_set>
#include <sys/stat.h>
#include <boost/filesystem.hpp>

namespace bfs = boost::filesystem;

#define DEFALT_TIMEOUT 10

//状态码描述
std::unordered_map<int, std::string> status_meg({
            {100, "Continue"},
            {101, "Switching Protocol"},
            {102, "Processing"},
            {103, "Early Hints"},
            {200, "OK"},
            {201, "Created"},
            {202, "Accepted"},
            {203, "Non-Authoritative Information"},
            {204, "No Content"},
            {205, "Reset Content"},
            {206, "Partial Content"},
            {207, "Multi-Status"},
            {208, "Already Reported"},
            {226, "IM Used"},
            {300, "Multiple Choice"},
            {301, "Moved Permanently"},
            {302, "Found"},
            {303, "See Other"},
            {304, "Not Modified"},
            {305, "Use Proxy"},
            {306, "unused"},
            {307, "Temporary Redirect"},
            {308, "Permanent Redirect"},
            {400, "Bad Request"},
            {401, "Unauthorized"},
            {402, "Payment Required"},
            {403, "Forbidden"},
            {404, "Not Found"},
            {405, "Method Not Allowed"},
            {406, "Not Acceptable"},
            {407, "Proxy Authentication Required"},
            {408, "Request Timeout"},
            {409, "Conflict"},
            {410, "Gone"},
            {411, "Length Required"},
            {412, "Precondition Failed"},
            {413, "Payload Too Large"},
            {414, "URI Too Long"},
            {415, "Unsupported Media Type"},
            {416, "Range Not Satisfiable"},
            {417, "Expectation Failed"},
            {418, "I'm a teapot"},
            {421, "Misdirected Request"},
            {422, "Unprocessable Entity"},
            {423, "Locked"},
            {424, "Failed Dependency"},
            {425, "Too Early"},
            {426, "Upgrade Required"},
            {428, "Precondition Required"},
            {429, "Too Many Requests"},
            {431, "Request Header Fields Too Large"},
            {451, "Unavailable For Legal Reasons"},
            {501, "Not Implemented"},
            {502, "Bad Gateway"},
            {503, "Service Unavailable"},
            {504, "Gateway Timeout"},
            {505, "HTTP Version Not Supported"},
            {506, "Variant Also Negotiates"},
            {507, "Insufficient Storage"},
            {508, "Loop Detected"},
            {510, "Not Extended"},
            {511, "Network Authentication Required"}
        });

// 根据后缀获取mime
        std::unordered_map<std::string, std::string> mimes({
            {".aac", "audio/aac"},
            {".abw", "application/x-abiword"},
            {".arc", "application/x-freearc"},
            {".avi", "video/x-msvideo"},
            {".azw", "application/vnd.amazon.ebook"},
            {".bin", "application/octet-stream"},
            {".bmp", "image/bmp"},
            {".bz", "application/x-bzip"},
            {".bz2", "application/x-bzip2"},
            {".csh", "application/x-csh"},
            {".css", "text/css"},
            {".csv", "text/csv"},
            {".doc", "application/msword"},
            {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
            {".eot", "application/vnd.ms-fontobject"},
            {".epub", "application/epub+zip"},
            {".gif", "image/gif"},
            {".htm", "text/html"},
            {".html", "text/html"},
            {".ico", "image/vnd.microsoft.icon"},
            {".ics", "text/calendar"},
            {".jar", "application/java-archive"},
            {".jpeg", "image/jpeg"},
            {".jpg", "image/jpeg"},
            {".js", "text/javascript"},
            {".json", "application/json"},
            {".jsonld", "application/ld+json"},
            {".mid", "audio/midi"},
            {".midi", "audio/x-midi"},
            {".mjs", "text/javascript"},
            {".mp3", "audio/mpeg"},
            {".mpeg", "video/mpeg"},
            {".mpkg", "application/vnd.apple.installer+xml"},
            {".odp", "application/vnd.oasis.opendocument.presentation"},
            {".ods", "application/vnd.oasis.opendocument.spreadsheet"},
            {".odt", "application/vnd.oasis.opendocument.text"},
            {".oga", "audio/ogg"},
            {".ogv", "video/ogg"},
            {".ogx", "application/ogg"},
            {".otf", "font/otf"},
            {".png", "image/png"},
            {".pdf", "application/pdf"},
            {".ppt", "application/vnd.ms-powerpoint"},
            {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
            {".rar", "application/x-rar-compressed"},
            {".rtf", "application/rtf"},
            {".sh", "application/x-sh"},
            {".svg", "image/svg+xml"},
            {".swf", "application/x-shockwave-flash"},
            {".tar", "application/x-tar"},
            {".tif", "image/tiff"},
            {".tiff", "image/tiff"},
            {".ttf", "font/ttf"},
            {".txt", "text/plain"},
            {".vsd", "application/vnd.visio"},
            {".wav", "audio/wav"},
            {".weba", "audio/webm"},
            {".webm", "video/webm"},
            {".webp", "image/webp"},
            {".woff", "font/woff"},
            {".woff2", "font/woff2"},
            {".xhtml", "application/xhtml+xml"},
            {".xls", "application/vnd.ms-excel"},
            {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
            {".xml", "application/xml"},
            {".xul", "application/vnd.mozilla.xul+xml"},
            {".zip", "application/zip"},
            {".3gp", "video/3gpp"},
            {".3g2", "video/3gpp2"},
            {".7z", "application/x-7z-compressed"},
        });

class Util
{
public:
    // 字符串分割函数，返回子串数量
    static ssize_t Split(std::string src, std::string spe, std::vector<std::string> *array)
    {
        // std::smatch m;
        // std::regex e(spe);
        // int re=std::regex_match(src,m,e);
        // DEBUG_LOG("SPLIST SRC");
        // for(auto&e:m){
        //     array->push_back(e);
        // }
        // return re;
        
        std::regex e(spe);
        std::sregex_token_iterator it(src.begin(), src.end(), e, -1);
        std::sregex_token_iterator end;

        array->clear(); // 清除旧数据
        while (it != end) {
            array->push_back(it->str());
            ++it;
        }

        return array->size(); // 返回分割后的元素数量

        // int count = 0, offset = 0;
        // while (1)
        // {
        //     size_t pos = src.find(spe, offset);
        //     if (pos == std::string::npos)
        //     {
        //         std::string s = src.substr(offset);
        //         array->push_back(s);
        //         count++;
        //         return count;
        //     }
        //     std::string s = src.substr(offset, pos - offset);
        //     array->push_back(s);
        //注意在这里硬编码是有问题的，因为要搜索的spe可能不是一个字符
        //     offset = pos + 1;
        //     count++;
        // }

        // return count;
    }

    // 读取文件内容
    static bool ReadFile(std::string filename, std::string* buf)
    {
        std::ifstream ifs(filename, std::ios::binary);
        if (ifs.is_open() == false) {
            INF_LOG("OPEN %s FILE FAILED!!", filename.c_str());
            return false;
        }
        size_t fsize = 0;
        ifs.seekg(0, ifs.end);//跳转读写位置到末尾
        fsize = ifs.tellg();  //获取当前读写位置相对于起始位置的偏移量，从末尾偏移刚好就是文件大小
        ifs.seekg(0, ifs.beg);//跳转到起始位置
        buf->resize(fsize); //开辟文件大小的空间
        ifs.read(&(*buf)[0], fsize);
        if (ifs.good() == false) {
            printf("READ %s FILE FAILED!!", filename.c_str());
            ifs.close();
            return false;
        }
        ifs.close();
        return true;
    }

    // 向文件写入内容
    static bool WriteFile(std::string filename, std::string buf)
    {
        std::ofstream ofs(filename, std::ios::binary | std::ios::trunc);
        if (ofs.is_open() == false) {
            printf("OPEN %s FILE FAILED!!", filename.c_str());
            return false;
        }
        ofs.write(buf.c_str(), buf.size());
        if (ofs.good() == false) {
            ERR_LOG("WRITE %s FILE FAILED!", filename.c_str());
            ofs.close();    
            return false;
        }
        ofs.close();
        return true;
    }
    //URL编码，避免URL中资源路径与查询字符串中的特殊字符与HTTP请求中特殊字符产生歧义
    //编码格式：将特殊字符的ascii值，转换为两个16进制字符，前缀%   C++ -> C%2B%2B
    //不编码的特殊字符： RFC3986文档规定 . - _ ~ 字母，数字属于绝对不编码字符
    //RFC3986文档规定，编码格式 %HH 
    //W3C标准中规定，查询字符串中的空格，需要编码为+， 解码则是+转空格
    // URL编码
    static std::string UrlEncode(const std::string url) {
        std::string res;
        for (auto &c : url) {
            //isalnum(c) 是一个在C和C++编程语言中常用的标准库函数，用于检查给定的字符 c 是否为字母（a-z 或 A-Z）或数字（0-9）。
            if (c == '.' || c == '-' || c == '_' || c == '~' || isalnum(c)) {
                res += c;
                continue;
            }
            if (c == ' ') {
                res += '+';
                continue;
            }
            //剩下的字符都是需要编码成为 %HH 格式
            char tmp[4] = {0};
            //snprintf 与 printf比较类似，都是格式化字符串，只不过一个是打印，一个是放到一块空间中
            //%%：表示字面量的 % 字符。想在输出中包含一个 % 字符，你需要使用两个连续的 % 符号来表示它（即 %%）。
            //这是因为单个 % 符号在格式字符串中被用作格式说明符的引导字符。
            //%02X：是一个格式说明符，表示将随后的整数参数格式化为两位宽的十六进制数，并在必要时前面填充零。
            snprintf(tmp, 4, "%%%02X", c);
            res += tmp;
        }
        return res;
    }

    // 返回对应的十进制数
    static int Todec(char c)
    {
        static std::unordered_map<char, int> maps({{'0', 0}, {'1', 1}, {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5}, {'6', 6}, {'7', 7}, {'8', 8}, {'9', 9}, {'A', 10}, {'B', 11}, {'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}});
        auto it = maps.find(c);
        if (it != maps.end())
        {
            return it->second;
        }
        return -1;
    }
    // URL解码
    //http://example.com/search?q=hello+world
    //在HTTP请求的路径（path）部分，加号（+）通常被直接解释为加号本身，而不是空格。
    //这是因为路径部分通常不包含空格，如果需要在路径中表示空格，通常会使用%20而不是加号。因此，在解析路径时，加号不需要被转换为空格。
    //在查询字符串（query string）部分，加号（+）通常被解释为空格。
    //这是因为查询字符串中经常需要表示空格，而加号是一个常用的表示空格的方式。加号则用%2B表示。因此，在解析查询字符串时，加号需要被转换为空格。
    //因此我们需要在这里加标志判断是解析路径还是查询字符串
    static std::string UrlDecode(const std::string &url,bool convert_plus_to_space)
    {
        std::string encode;
        for (int i = 0; i < url.size(); i++)
        {
            if (url[i] == '%' && i + 2 < url.size())
            {
                int bbit = Todec(url[i] + 1);
                int tbit = Todec(url[i] + 2);
                char c = tbit * 16 + bbit;
                encode += c;
                i += 2;
            }
            else if (url[i] == '+'&&convert_plus_to_space==true)
            {
                encode += ' ';
            }
            else
            {
                encode += url[i];
            }
        }
        return encode;
    }
    // 通过HTTP状态码获取描述信息
    static std::string StatuDesc(int statu)
    {
        auto it = status_meg.find(statu);
        if (it != status_meg.end())
        {
            return it->second;
        }
        return "UNFIND";
    }
    // 根据文件名后缀获取mime
    static std::string ExtMime(std::string filename)
    {
        // 获取后缀
        int pos=filename.rfind(".");
        if(pos==filename.npos){
             return "UNFIND";
        }
        auto it = mimes.find(filename.substr(pos));
        if (it != mimes.end())
        {
            return it->second;
        }

        return "UNFIND";
    }

    // 判断一个文件是否是一个目录
    static bool IsDirectory(std::string filename)
    {
        bfs::path p(filename);
        return bfs::is_directory(p);
    }
    // 判断一个文件是否是一个普通文件
    static bool IsRegular(std::string filename)
    {
        bfs::path p(filename);
        return bfs::is_regular_file(p);
    }
    // http请求的资源路径有效性判断
    // /index.html  --- 前边的/叫做相对根目录  映射的是某个服务器上的子目录
    // 想表达的意思就是，客户端只能请求相对根目录中的资源，其他地方的资源都不予理会
    // /../login, 这个路径中的..会让路径的查找跑到相对根目录之外，这是不合理的，不安全的
    //注意在这里我们不需要判断文件是否存在只需要判断文件路径请求是否合法
    static bool ValidPath(std::string filepath)
    {
        std::vector<std::string> files;
        int level=0;
        Util::Split(filepath,"/",&files);
        for(auto& f:files){
            if(f==".."){
                level--;
                if(level<0) 
                {
                    DEBUG_LOG("ValidPath ERR");
                    return false;
                }
            }
            else 
                level++;
        }
        return true;
    }
};

//Http请求
class HttpRequest{
public:
    //std::string _httpmessage;//Http报文
    std::smatch _matches;//存储Http请求报文首行
    std::string _method;//http请求报文首行方法
    std::string _path;//http请求报文首行资源地址
    std::unordered_map<std::string,std::string> _params;//http请求报文首行查询关键字
    std::string _version;//http请求报文首行http版本
    std::unordered_map<std::string,std::string> _headcontents;//Http请求报文头部
    std::string _body;//Http请求报文正文
public:
    HttpRequest(){}
    //重置请求报文
    void Reset(){
        std::smatch match;
        _matches.swap(match);
        _method.clear();
        _path.clear();
        _params.clear();
        _version.clear();
        _headcontents.clear();
        _body.clear();
    }
    //插入报头属性
    void SetHeader(std::string k,std::string v){
        _headcontents.insert(std::make_pair(k,v));
    }
    //查询报头属性
    bool HashReqHead(std::string property)const{
        auto it=_headcontents.find(property);
        if(it!=_headcontents.end()){
            return true;
        }
        return false;
    }
    //获取报头属性
    std::string GetHeadPro(std::string pro)const{
        // if(HashReqHead(pro)) return _headcontents[pro];
        // return "NOTEXITS";
        auto it = _headcontents.find(pro);  
        if (it != _headcontents.end()) {  
            return it->second; // 如果找到，返回对应的值  
        }  
        return "NOTEXISTS"; // 如果没有找到，返回"NOTEXISTS"  
    }
    //判断是否是短连接
    bool Close()const{
        // DEBUG_LOG("%d",HashReqHead("Connection")==true);
        // DEBUG_LOG("%d",GetHeadPro("Connection")=="keep-alive");
        // DEBUG_LOG("%s",GetHeadPro("Connection").c_str());
        //要注意keep-aliv\r\n和keep-alive是不相等的
        if(HashReqHead("Connection")==true&& GetHeadPro("Connection")=="keep-alive"){
            return false;
        }
        return true;
    }
    //设置http请求报文首行查询关键字
    void InsertParm(std::string key,std::string value){
        _params.insert(std::make_pair(key,value));
    }

    //设置Http请求报文首行以及解析首行
    void SetReqline(std::smatch matches){
    }
    //设置请求正文
    void SetContent(std::string body){
        _body=body;
    }
    //查看正文长度
    size_t GetHttpBodyLen(){
        // if(HashReqHead("Content-Length")) return std::stoi((_headcontents["Content-Length"]));
        // return -1;
        //没有这个属性则返回0，正文长度不能返回负数
        bool ret = HashReqHead("Content-Length");
        if (ret == false) {
            return 0;
        }
        std::string clen = GetHeadPro("Content-Length");
        return std::stol(clen);
    }
    //查询字符串
    bool HashReqParam(std::string param){
        auto it=_params.find(param);
        if(it!=_params.end()){
            return true;
        }
        return false;
    }
    //返回查询字符串
    std::string GetWord(std::string param){
        if(HashReqParam(param)) return _headcontents[param];
        return "NOTEXITS";
    }
    //返回请求方法
    std::string GetReqmethod(){
        return _method;
    }
    //返回资源请求地址
    std::string GetUrl(){ 
        return _path;
    }
    //返回Http版本
    std::string GetHttpVer(){
        return _version;
    }
};




//Http响应报文模块
class HttpResponse{
public:
    //std::string _httpmessage;//Http响应报文
    //std::smatch _m;//存储响应报文首行
    int _statu;//状态码
    std::string _statu_meg;//状态描述
    std::string _http_ver;//http版本
    std::unordered_map<std::string,std::string> _headers;//Http报文响应头部
    std::string _body;//Http响应报文正文
    bool _redirect_flag;//重定向标志
    std::string _redirect_url;//重定向url
private:
public:
    HttpResponse(int statu=200):_statu(statu),_http_ver("http/1.1"){}
    //插入报头属性
    void SetHeader(std::string k,std::string v){
        _headers.insert(std::make_pair(k,v));
    }
    //查询报头属性
    bool HasHeader(std::string property)const{
        auto it=_headers.find(property);
        if(it!=_headers.end()){
            return true;
        }
        return false;
    }
    //std::unordered_map的[]操作符用于访问或插入元素。
    //然而，当std::unordered_map被声明为const时，你不能使用[]操作符，因为[]可能会插入一个新元素（如果键不存在的话）。插入操作会修改容器，而const对象是不允许被修改的。
    //获取报头属性
    std::string GetHeadPro(std::string pro)const{
        // if(HasHeader(pro)) return _headers[pro];
        // return "NOTEXITS";
        auto it = _headers.find(pro);  
        if (it != _headers.end()) {  
            return it->second; // 如果找到，返回对应的值  
        }  
        return "NOTEXISTS"; // 如果没有找到，返回"NOTEXISTS"  
    }
    //设置Http响应状态码
    void SetStatucode(int code){
        _statu=code;
        _statu_meg=Util::StatuDesc(_statu);
    }
    void SetHttpVer(std::string ver){
        _http_ver=ver;
    }
    //设置请求正文
    void SetContent(std::string body,std::string type){
        _body=body;
        SetHeader("Content-Type",type);
    }
    //设置重定向
    void SetRedirect(const std::string &url, int statu = 302) {
        _statu = statu;
        _redirect_flag = true;
        _redirect_url = url;
    }
    //判断是否是长连接
    bool Close()const{
        if(HasHeader("Connection")==true&& GetHeadPro("Connection")=="keep-alive"){
            return false;
        }
        return true;
    }
    //查看正文长度
    int GetHttpBodyLen(){
        if(HasHeader("Content-Length")) return std::stoi((_headers["Content-Length"]));
        return 0;
    }
};

enum HttpRecvStage{
    RECV_HTTP_LINE,
    RECV_HTTP_HEAD,
    RECV_HTTP_BOBY,
    RECV_HTTP_OVER,
    RECV_HTTP_ERROR
};

//一行的最大数据量,单位字节
#define MAX_LINE 8192
//协议上下文模块
class HttpContext{
private:
    HttpRecvStage _resq_stage;//当前接收及解析的阶段状态
    int _resp_statu;//响应状态码
    HttpRequest _request;//已经解析得到的请求信息
private:
    //解析·请求报文首行
    bool ParseHttpLine(std::string line){
        // std::regex e("(GET|HEAD|POST|PUT|DELETE) ([^?].*)(?:\\?[.*])? (Http/1\\.[01])(?:\n|\r\n)?", std::regex::icase);
        // std::smatch matches;
        // bool re=std::regex_match(line,matches,e);
        // //解析错误，请求资源有问题
        // if(re==false) 
        // {
        //     DEBUG_LOG(":regex_match ERR");
        //     _resp_statu=400;
        //     _resq_stage=RECV_HTTP_ERROR;
        //     return false;
        //}
        //std::smatch matches;
        std::smatch matches;
        //(?:\\?(.*))? 这部分是一个非捕获组，用于匹配可选的查询字符串。如果查询字符串不存在，这个部分将不会捕获任何内容，matches[3] 将是一个空字符串。
        std::regex e("(GET|HEAD|POST|PUT|DELETE) ([^?]*)(?:\\?(.*))? (HTTP/1\\.[01])(?:\n|\r\n)?", std::regex::icase);
        bool ret = std::regex_match(line, matches, e);
        if (ret == false) {
            _resq_stage = RECV_HTTP_ERROR;
            _resp_statu = 400;//BAD REQUEST
            return false;
        }
        //0 : GET /bitejiuyeke/login?user=xiaoming&pass=123123 HTTP/1.1
        //1 : GET
        //2 : /bitejiuyeke/login
        //3 : user=xiaoming&pass=123123
        //4 : HTTP/1.1
        //请求方法的获取
        _request._method = matches[1];
        std::transform(_request._method.begin(), _request._method.end(), _request._method.begin(), ::toupper);
        //DEBUG_LOG("urlcode front %s",matches[2]);
        //资源路径的获取，需要进行URL解码操作，但是不需要+转空格
        _request._path = Util::UrlDecode(matches[2].str(), false);
        //DEBUG_LOG("urlcode finish %s", _request._path);
        //协议版本的获取
        _request._version = matches[4];
        //查询字符串的获取与处理
        std::vector<std::string> query_string_arry;
        std::string query_string = matches[3];
        //查询字符串的格式 key=val&key=val....., 先以 & 符号进行分割，得到各个字串
        Util::Split(query_string, "&", &query_string_arry);
        //针对各个字串，以 = 符号进行分割，得到key 和val， 得到之后也需要进行URL解码
        for (auto &str : query_string_arry) {
            size_t pos = str.find("=");
            if (pos == std::string::npos) {
                _resq_stage = RECV_HTTP_ERROR;
                _resp_statu = 400;//BAD REQUEST
                return false;
            }
            std::string key = Util::UrlDecode(str.substr(0, pos), true);  
            std::string val = Util::UrlDecode(str.substr(pos + 1), true);
            _request.InsertParm(key, val);
        }
        return true;
        // //获取请求方法
        // _request._method=m[1].str();
        // //
        // int pos=m[2].str().find('?');
        // if(pos!=_request._path.npos){
        //     //DEBUG_LOG("SPLIT");
        //     std::string s=(std::string)(m[2].str()).substr(0,pos);
        //     _request._path=Util::UrlDecode(s,false);
        //     std::string str=m[2].str().substr(pos+1);
        //     std::vector<std::string> words;
        //     //DEBUG_LOG("%s",str.c_str());
        //     Util::Split(str,"&",&words);
        //     for(int i=0;i<words.size();i++){
        //         std::vector<std::string> word;
        //         Util::Split(words[i],"=",&word);
        //         //查询字符串也需要解码
        //         if(word.size()==2){
        //             std::string key=Util::UrlDecode(word[0],true);
        //             std::string value=Util::UrlDecode(word[1],true);
        //             _request.InsertParm(key,value);
        //         }
        //     }
        // }
        // else{
        //     _request._path=m[2].str();
        // }    
        // _request._version=m[3].str();
        // _resq_stage=RECV_HTTP_HEAD;
        // return true;
    }
    //接收请求报文首行
    bool RecvHttpLine(Buffer* buf){
        std::string str=buf->GetLineAndPop();
        if(str.size()!=0){
            return ParseHttpLine(str);
        }
        return false;
    }
    //解析·请求报文头部
    bool ParseHttpHead(std::string str){
        std::vector<std::string> array;
        Util::Split(str,": ",&array);
        std::string k=array[0];
        std::string v;
        bool flag=false;
        for(int i=1;i<array.size();i++){
            if(flag){
                v+=":";
            }
            v+=array[i];
            flag=true;
        }
        _request.SetHeader(k,v);
        return true;
    }
    //接收请求报文头部
    bool RecvHttpHead(Buffer* buf){
        std::string str;
        int count=0;
        while(1){
            str=buf->GetLineAndPop();
            if(str=="\r\n"){
                _resq_stage=RECV_HTTP_BOBY;
                return true;
            }
            if(str.size()==0){
                return false;
            }
            //去掉\r\n方便后续比较，在后面发送响应报文时也会添加\r\n
            if(str.back()=='\n') str.pop_back();
            if(str.back()=='\r') str.pop_back();
            ParseHttpHead(str);
        }
    }
    //在请求报文正文中的不需要拿出来
    //接收请求报文正文
    bool RecvBoby(Buffer* buf){
        int len=_request.GetHttpBodyLen();
        //DEBUG_LOG("Len:%d",len);
        if(buf->ReadAbleSize()>=len){
            std::string boby=buf->ReadAsStringAndPop(len);
            _request.SetContent(boby);
            //_request.InsertParm(boby);
        }
        else{ 
            return false;
        }
        _resq_stage=RECV_HTTP_OVER;
        return true;
    }

public:
    HttpContext():_resp_statu(200),_resq_stage(RECV_HTTP_LINE){}
    //重置上下文
    void ReSet(){
        _resp_statu=200;
        _resq_stage=RECV_HTTP_LINE;
        _request.Reset();
    }
    //返回阶段状态
    HttpRecvStage RecvStage(){
        return _resq_stage;
    }
    //返回状态码
    int RespStatu(){
        return _resp_statu;
    }
    //返回状态码描述
    std::string GetStatuDesc(){
        return Util::StatuDesc(_resp_statu);
    }
    //返回已经解析得到的请求信息
    HttpRequest& Request(){
        return _request;
    }
    //Http处理
    void RecvHttpRequest(Buffer* buf){
        if(_resq_stage==RECV_HTTP_LINE){
            RecvHttpLine(buf);
        }
        if(_resq_stage==RECV_HTTP_HEAD){
            RecvHttpHead(buf);
        }
        if(_resq_stage==RECV_HTTP_BOBY){
            RecvBoby(buf);
        }
        if(_resq_stage==RECV_HTTP_OVER){
            INF_LOG("HTTP OVER");
        }
    }
};


class HttpServer{
private:
    //在映射表里，如何请求有有数字比如 desc/1234,难道我们还要专门写一个函数来映射嘛？写了desc/1234,那desc/12写不写？desc21呢？
    //正则表达式出动
    using func=std::function<void(HttpRequest&,HttpResponse*)>;
    using Handlers=std::vector<std::pair<std::regex,func>>;
    Handlers _post_route;
    Handlers _get_route;
    Handlers _put_route;
    Handlers _delete_route;
    std::string _basedir;//根目录
    TcpServer _tcpserver;
public:
    void OnClosed(const PtrConnection &conn){
        //DEBUG_LOG("Close CONNECTION:%p:",conn.get());
    }
    //初始化上下文
    void OnConnected(const PtrConnection &conn){
        conn->SetContext(HttpContext());
        DEBUG_LOG("NEW CONNECTION:%p:",conn.get());
    }

    //错误网页返回
    void ErrHtml(HttpResponse*rep){
        //1. 组织一个错误展示页面
        std::string body;
        body += "<html>";
        body += "<head>";
        body += "<meta http-equiv='Content-Type' content='text/html;charset=utf-8'>";
        body += "</head>";
        body += "<body>";
        body += "<h1>";
        body += std::to_string(rep->_statu);
        body += " ";
        body += Util::StatuDesc(rep->_statu);
        body += "</h1>";
        body += "</body>";
        body += "</html>";
        //2. 将页面数据，当作响应正文，放入rep中
        rep->SetContent(body, "text/html");
    }

    //静态资源的请求处理
    bool WriteReponse(HttpRequest& req,HttpResponse*rep){
        //DEBUG_LOG("WriteReponse");
        // if(req._headcontents.size()!=0){
        //     return false;
        // }
        std::string path=_basedir+req.GetUrl();
        std::string content;
        if(req.GetUrl()=="/"){
            path+="index.html";
        }
        //文件路径有效才执行后续文件读写
        if(!Util::ValidPath(path)){
            //DEBUG_LOG("ValidPath ERR");
            //rep->SetStatucode(400);
            return false;
        }
        if(!Util::ReadFile(path,&content)){
            return false;
        }
        //添加资源类型
        rep->SetStatucode(200);
        std::string remime=Util::ExtMime(path);
        rep->SetContent(content,remime);
    
        //添加正文长度，
        //rep->SetHeader("Content-Length",std::to_string(sizeof(content)));  
    }
    //单个路由选择
    void Route_Dispatcher(HttpRequest& req,HttpResponse*rep,Handlers& handlers){
        for(auto handler:handlers){
            //DEBUG_LOG("PATH:%s",req._path);
            if(std::regex_match(req._path,handler.first)){
                handler.second(req,rep);
                return;
            }
        }
        rep->SetStatucode(404);
    }
    //功能性请求的分类处理
    //switch语句不能直接用于字符串（如std::string），因为switch语句的case标签必须是整型常量表达式或枚举值。
    void Dispatcher(HttpRequest& req,HttpResponse*rep){
        if(req.GetReqmethod()=="POST"){
            Route_Dispatcher(req,rep,_post_route);
        }
        else if(req.GetReqmethod()=="GET"){
            Route_Dispatcher(req,rep,_get_route);
        }
        else if(req.GetReqmethod()== "PUT"){
            Route_Dispatcher(req,rep,_put_route);            
        }
        else if(req.GetReqmethod()== "DELETE"){
            Route_Dispatcher(req,rep,_delete_route);
        } else{
            rep->SetStatucode(405);
        }
    }
    //路由查找
    void Route(HttpRequest& req,HttpResponse*rep){
        if(WriteReponse(req,rep)){
            return;
        }
        Dispatcher(req,rep);
    }
    //返回响应报文
    //通过请求补充响应报文
    void WriteContent(const PtrConnection &conn, const HttpRequest &req,HttpResponse& rep){
        // std::string rspcontent;
        // rspcontent+=rep._http_ver;
        // rspcontent+=' ';
        // rspcontent+=std::to_string(rep._statu);
        // rspcontent+=' ';
        // rspcontent+=rep._statu_meg;
        // rspcontent+="\r\n";
        // std::unordered_map<std::string,std::string> headcontents=rep._headers;
        // auto it=headcontents.begin();
        // while(it!=headcontents.end()){
        //     rspcontent+=it->first;
        //     rspcontent+=':';
        //     rspcontent+=it->second;
        //     rspcontent+="\r\n";
        //     it++;
        // }
        // rspcontent+="\r\n";
        // rspcontent+=rep._body;
        // //rspcontent+="\r\n";
        // DEBUG_LOG("SEND:%s",rspcontent.c_str());
        // conn->Send((char*)rspcontent.c_str(),rspcontent.size());

        if (req.Close() == true) {
            rep.SetHeader("Connection", "close");
        }else {
            rep.SetHeader("Connection", "keep-alive");
        }
        if (rep._body.empty() == false && rep.HasHeader("Content-Length") == false) {
            rep.SetHeader("Content-Length", std::to_string(rep._body.size()));
        }
        if (rep._body.empty() == false && rep.HasHeader("Content-Type") == false) {
            rep.SetHeader("Content-Type", "application/octet-stream");
        }
        if (rep._redirect_flag == true) {
            rep.SetHeader("Location", rep._redirect_url);
        }
        //2. 将rsp中的要素，按照http协议格式进行组织
        std::stringstream rsp_str;
        rsp_str << req._version << " " << std::to_string(rep._statu) << " " << Util::StatuDesc(rep._statu) << "\r\n";
        for (auto &head : rep._headers) {
            rsp_str << head.first << ": " << head.second << "\r\n";
        }
        rsp_str << "\r\n";
        rsp_str << rep._body;
        //DEBUG_LOG("%s",rsp_str.str().c_str());
        conn->Send((char*)rsp_str.str().c_str(), rsp_str.str().size());
    }
    //需要考虑如果不是一个完整的报文到来怎么办
    void OnMessage(const PtrConnection &conn,Buffer*buf){
        while(1){
            //将数据解析放到一个HttpRequest中；
            //解析不成功怎么办？
            //解析的不是一条完整的报文怎么办？
            //DEBUG_LOG("%s",buf->ReadPosition());
            Any*a=conn->GetContext();
            //HttpContext* text=a->getVal<HttpContext>();
            HttpContext* text=a->getVal<HttpContext>();
            text->RecvHttpRequest(buf);

            HttpRequest req=text->Request();
            //设置状态码
            HttpResponse rep(text->RespStatu());
            //请求解析不成功
            if(rep._statu>=400){
                ErrHtml(&rep);
                WriteContent(conn,(const HttpRequest)req,rep);
                //出错了，直接缓冲区里面的数据清零，不然要将里面的数据取完才能关闭连接，因为我们设置了读缓冲区里面有数据就要进行处理
                buf->MoveReadOffset(buf->ReadAbleSize());
                //初始化上下文
                text->ReSet();
                //关闭连接
                conn->Shutdown();
                return;
            }
            //收到的不是一条完整报文
            if(text->RecvStage()!=RECV_HTTP_OVER){
                //DEBUG_LOG("NOT Full request");
                return; 
            }
            //查找映射的函数调用
            Route(req,&rep);
            //解析不成功
            if(rep._statu>=400){
                ErrHtml(&rep);
                WriteContent(conn,(const HttpRequest)req,rep);
                text->ReSet();
                conn->Shutdown();
                return;
            }
            //组装成响应报文发送
            WriteContent(conn,(const HttpRequest)req,rep);
            //将处理后的结果写到发送缓冲区中
            //重置上下文,保证下一条报文的处理不会受上一条的影响,因为如果是长连接，那么上下文里面残留的数据可能会影响下一条报文的处理
            text->ReSet();
            //判断是否是短连接,是直接关闭连接,是长连接则继续处理
            if(rep.Close())
                conn->Shutdown();
        }
    }
public:
    HttpServer(int port,int timeout=DEFALT_TIMEOUT):_tcpserver(port){
        _tcpserver.EnableInactiveRelease(timeout);

        _tcpserver.SetMessageCallback(std::bind(&HttpServer::OnMessage,this,std::placeholders::_1,std::placeholders::_2));
        _tcpserver.SetClosedCallback(std::bind(&HttpServer::OnClosed,this,std::placeholders::_1));
        _tcpserver.SetConnectedCallback(std::bind(&HttpServer::OnConnected,this,std::placeholders::_1));
    }
    //添加映射函数
    //在 C++ 中，std::unordered_map 的 insert 方法通常不接受 std::make_pair 的直接调用，
    //尤其是当键的类型是 std::basic_regex<char> 时。这可能是因为 std::basic_regex 可能不支持作为哈希表的键，或者需要特殊的哈希函数和比较函数。
    void Post(std::string e,func f){
        _post_route.push_back(make_pair(std::regex(e),f));
    }
    void Get(std::string e,func f){
        _get_route.push_back(make_pair(std::regex(e),f));
    }
    void Put(std::string e,func f){
        _put_route.push_back(make_pair(std::regex(e),f));
    }
    void Delete(std::string e,func f){
        _delete_route.push_back(make_pair(std::regex(e),f));
    }
    void SetBaseDir(const std::string& path){
        _basedir=path;
    }
    //设置Loop线程池数量
    void SetThreadCount(int thread_count){_tcpserver.SetThreadCount(thread_count);}
    //void CreateTHreadPool(){_tcpserver.CreateTHreadPool();};
    //启动非活跃销毁
    void EnableInactiveRelease(int timeout){
        _tcpserver.EnableInactiveRelease(timeout);
    }
    // //取消非活跃销毁
    // void CancelRelease(){
    //     _tcpserver.CancelRelease();
    // }
    //启动服务器
    void Listen(){
        //CreateTHreadPool();
        _tcpserver.Start();
    }
};
